package com.template.spring.beerportal.domain;

import static javax.persistence.GenerationType.IDENTITY;

import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.PersistenceContext;
import javax.persistence.Table;
import javax.persistence.Version;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.transaction.annotation.Transactional;

@Configurable
@Entity
@Table(name = "beer")
public class Beer {

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "BEER_ID", unique = true, nullable = false)
	private Long id;

	@Version
	@Column(name = "version")
	private Integer version;

	@ManyToMany(fetch = FetchType.LAZY, mappedBy = "beers")
	Set<Bar> bars;

	@Column(name = "NAME", unique = true, nullable = false, length = 128)
	private String name;

	public String toString() {
		return ReflectionToStringBuilder.toString(this,
				ToStringStyle.SHORT_PREFIX_STYLE);
	}

	public Long getId() {
		return this.id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public Set<Bar> getBars() {
		return bars;
	}

	public void setBars(Set<Bar> bars) {
		this.bars = bars;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@PersistenceContext
	transient EntityManager entityManager;

	public EntityManager getEntityManager() {
		return this.entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	public static final EntityManager entityManager() {
		EntityManager em = new Beer().entityManager;
		if (em == null)
			throw new IllegalStateException(
					"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
		return em;
	}

	public static long countBeers() {
		return entityManager().createQuery("SELECT COUNT(o) FROM Beer o",
				Long.class).getSingleResult();
	}

	public static List<Beer> findAllBeers() {
		return entityManager().createQuery("SELECT o FROM Beer o", Beer.class)
				.getResultList();
	}

	public static Beer findBeer(Long id) {
		if (id == null)
			return null;
		return entityManager().find(Beer.class, id);
	}

	public static List<Beer> findBeerEntries(int firstResult, int maxResults) {
		return entityManager().createQuery("SELECT o FROM Beer o", Beer.class)
				.setFirstResult(firstResult).setMaxResults(maxResults)
				.getResultList();
	}

	@Transactional
	public void persist() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.persist(this);
	}

	@Transactional
	public void remove() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		if (this.entityManager.contains(this)) {
			this.entityManager.remove(this);
		} else {
			Beer attached = Beer.findBeer(this.id);
			this.entityManager.remove(attached);
		}
	}

	@Transactional
	public void flush() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.flush();
	}

	@Transactional
	public void clear() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.clear();
	}

	@Transactional
	public Beer merge() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		Beer merged = this.entityManager.merge(this);
		this.entityManager.flush();
		return merged;
	}

}
